#region
/* Adoor.NET - Object/Relational mapping framework leveraging ADO.NET`s powerful disconnected mode.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *  
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *  
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */ 
#endregion

using System;
using System.Collections.Generic;
using System.Configuration;
using Adoor.Object.Domain;
using Adoor.Object.Entity;
using Adoor.Object.Query;

using System.ComponentModel;
using System.Drawing.Design; 

namespace Adoor.Object.Domain
{
	/// <summary>
	/// The object which describes the entities and their relationships.
	/// </summary>
//    [
//Editor("Adoor.VSDesigner.CollectionEditor.LinkedDomainGroupEditor, Adoor.VSDesigner", typeof(UITypeEditor))]
    //[Editor(typeof(EditorTest3), typeof(UITypeEditor))]
    public class ObjectDomain : ICustomTypeDescriptor  //System.ComponentModel.Component// UML Category ?
	{
        private EntityDependancyRegistry objectDependencies = null;

        public EntityDependancyRegistry ObjectDependencies
        {
            get { return objectDependencies; }
        }

        public ObjectDomain() : this(new LinkedDomainGroup())
        {
            
        }

        public ObjectDomain(LinkedDomainGroup domainGroup):this(domainGroup,String.Empty)  
        {
            
        }

		/// <summary>
		/// Creates a new <see cref="ObjectDomain"/>.
		/// </summary>
        public ObjectDomain(LinkedDomainGroup domainGroup, string name)
		{
            this.domainGroup = domainGroup;
			this.entityDataCollection = new EntityDataCollection(this);
            this.name = name;
            this.objectDependencies = new EntityDependancyRegistry(this);   
		}
        /// <summary>
        /// Allows per domains lookups and resolution <see cref="IObjectResolver"/>
        /// </summary>
        [Browsable(false)]
        public IObjectResolver ObjectResolver
        {
            get
            {
                return domainGroup.ObjectResolver;
            }
        }

        private LinkedDomainGroup domainGroup;
        /// <summary>
        /// Domain Group to which the current instance belongs to.
        /// </summary>
        [Browsable(false)]
        public LinkedDomainGroup DomainGroup
		{
            get { return domainGroup; }
			set
			{
                if (this.domainGroup == null)
                    this.domainGroup = value;
			}
		}

		private bool built;
        /// <summary>
        /// Build current domain
        /// </summary>
		public void Build()
		{
			if (!built)
			{
				built = true;
                //if(AppSettingsPath.UseAOP)
                //    Adoor.Object.Domain.DomainBuild.AOP.ObjectDomainBuilder.Build(this, this.assemblyName, this.mapFileName);
                //else
                if(mapFileName==null)
                    Adoor.Object.Domain.DomainBuild.CodeDom.ObjectDomainBuilder.Build(this, this.assemblyName);
                else
                    Adoor.Object.Domain.DomainBuild.CodeDom.ObjectDomainBuilder.Build(this, this.assemblyName, this.mapFileName);
			}
			foreach(ObjectDomain refDomain in References)
			{
				refDomain.Build();
			}
		}

		private string name;
        /// <summary>
        /// Domain name
        /// </summary>
        [Category("Behavior"),
DescriptionAttribute("Domain Group"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
		public string Name
		{
			get { return this.name; }
		}

		private string assemblyName;
		/// <summary>
		/// The assembly containing the entity classes for this domain.
		/// </summary>
		public string AssemblyName
		{
			get { return this.assemblyName; }
			set { this.assemblyName = value; }
		}

		private string mapFileName;
		/// <summary>
		/// The name of the xml file as an embedded resource.
		/// </summary>
		public string MapFileName
		{
			get { return this.mapFileName; }
			set { this.mapFileName = value; }
		}

		/// <summary>
		/// Gets the collection of <see	cref="EntityData"/> objects.
		/// </summary>
		/// <value>
		/// A collection that contains <see cref="EntityData"/> objects.
		/// </value>
        [Browsable(false)]
        public EntityDataCollection EntityInfos
		{ 
			get
			{
				Build();
				return this.entityDataCollection; 
			}
		}

        /// <summary>
        /// Add an <see cref="EntityData"/> object to EntityInfos collection
        /// </summary>
        /// <param name="type"></param>
        /// <param name="entityData"></param>
		public void RegisterEntityData(Type type, EntityData entityData)
		{
			this.entityDataCollection.Add(type, entityData);
		}

        private List<ObjectDomain> references = new List<ObjectDomain>();
        /// <summary>
        /// A collection of <see cref="ObjectDomain"/> objects that are referenced by current instance
        /// </summary>
        public List<ObjectDomain> References
		{
			get
			{
				//Build();
				return this.references; 
			}
		}

		private EntityDataCollection entityDataCollection;

        #region ICustomTypeDescriptor Members

        public AttributeCollection GetAttributes()
        {
            return TypeDescriptor.GetAttributes(this, true);
        }

        public string GetClassName()
        {
            return TypeDescriptor.GetClassName(this, true);
        }

        public string GetComponentName()
        {
            return TypeDescriptor.GetComponentName(this, true);
        }

        public TypeConverter GetConverter()
        {
            return TypeDescriptor.GetConverter(this, true);
        }

        public EventDescriptor GetDefaultEvent()
        {
            return TypeDescriptor.GetDefaultEvent(this, true);
        }

        public PropertyDescriptor GetDefaultProperty()
        {
            return TypeDescriptor.GetDefaultProperty(this, true);
        }

        public object GetEditor(Type editorBaseType)
        {
            return TypeDescriptor.GetEditor(this, editorBaseType, true);
        }

        public EventDescriptorCollection GetEvents(Attribute[] attributes)
        {
            return TypeDescriptor.GetEvents(this, attributes, true);
        }

        public EventDescriptorCollection GetEvents()
        {
            return TypeDescriptor.GetEvents(this, true);
        }

        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            return TypeDescriptor.GetProperties(this, attributes, true);
        }

        public PropertyDescriptorCollection GetProperties()
        {
            return TypeDescriptor.GetProperties(this, true);
        }

        public object GetPropertyOwner(PropertyDescriptor pd)
        {
            return this;
        }

        #endregion
	}
}